use core::fmt::{Display, Formatter};
use derive_builder::Builder;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

use crate::error::Error;
use crate::modeling::Value;

///```json
///{
///    "refer_wav_path": "123.wav",
///    "prompt_text": "一二三。",
///    "prompt_language": "zh",
///    "text": "先帝创业未半而中道崩殂，今天下三分，益州疲弊，此诚危急存亡之秋也。",
///    "text_language": "zh"
///}
///```
#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]

pub struct TtsRequestMessage {
    pub prompt_audio_path: Option<String>,
    pub prompt_language: Option<String>,
    pub prompt_text: Option<String>,
    pub text: String,
    pub text_language: Option<String>,
}

#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
pub struct TtsRequestOptions {
    pub model: Option<String>,
    pub local_file: Option<String>,
    pub extensions: Option<HashMap<String, String>>,
}

#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
pub struct TtsResponseMessage {
    pub options: HashMap<String, String>,
    pub audio: Vec<u8>,
}

impl TtsRequestMessage {}

impl TtsResponseMessage {
    pub fn new(audio: Vec<u8>) -> anyhow::Result<Self> {
        Ok(Self {
            options: HashMap::new(),
            audio: audio,
        })
    }
}

impl TryFrom<Value> for TtsRequestMessage {
    type Error = anyhow::Error;

    fn try_from(value: Value) -> Result<Self, Self::Error> {
        let serde_value: serde_json::Value = value.try_into()?;
        let message = serde_json::from_value(serde_value)?;
        Ok(message)
    }
}

impl TryInto<Value> for TtsRequestMessage {
    type Error = anyhow::Error;

    fn try_into(self) -> Result<Value, Self::Error> {
        Value::try_from(serde_json::json!(self))
    }
}

impl TtsRequestOptions {
    pub fn new() -> anyhow::Result<Self> {
        Ok(Self {
            model: None,
            extensions: None,
            local_file: None,
        })
    }
}
